package com.mjk.common.core.jdbc.util.provider;

import com.mjk.common.base.model.BaseEntity;
import com.mjk.common.base.model.BaseExample;
import com.mjk.common.core.jdbc.annotation.*;
import com.mjk.common.core.jdbc.ibatis.typehandler.BaseHandler;
import com.mjk.common.core.jdbc.ibatis.typehandler.handler.SerialBlobTypeHandler;
import com.mjk.common.core.jdbc.ibatis.typehandler.handler.SerialClobTypeHandler;
import com.mjk.common.core.jdbc.service.plus.constns.BeeTypeEntity;
import com.mjk.common.core.jdbc.service.plus.provider.BeeDataSourceType;
import com.mjk.common.core.jdbc.service.plus.provider.interfaces.IBeeProvider;
import com.mjk.common.core.jdbc.service.plus.provider.interfaces.IBeeTypeMapping;
import com.mjk.common.core.jdbc.service.plus.wrap.BeeComplexQueryWrapper;
import com.mjk.common.core.jdbc.util.TableUtils;
import com.mjk.common.tools.logger.BizLogger;
import com.mjk.common.util.ObjectUtils;
import com.mjk.common.util.ReflectionUtils;
import com.mjk.common.util.StrUtils;
import org.apache.ibatis.type.JdbcType;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

/**
 * sql语句提供抽象类
 */
public class SqlProvider {
    /**
     * 通过example 获取对应的entity 实例
     *
     * @param example
     * @return
     */
    public static BaseEntity getEntityFromExample(BaseExample example) {
        try {
            return (BaseEntity) Class.forName(example.getClass().getName().replace("Example", "")).newInstance();
        } catch (Exception e) {
            BizLogger.error(e);
        }
        return null;
    }

    /**
     * 更具example 获取对应的 entity 类型
     *
     * @param example
     * @return
     */
    public static Class<BaseEntity> getEntityClassFromExample(BaseExample example) {
        try {
            return (Class<BaseEntity>) Class.forName(example.getClass().getName().replace("Example", ""));
        } catch (Exception e) {
            BizLogger.error(e);
        }
        return null;
    }

    /**
     * 根据BaseEntity的条件转为Excample
     *
     * @param t
     * @param <T>
     * @return
     */
    public static <T extends BaseEntity> BaseExample createExample(T t) {
        try {
            List<Field> fields = getValidTableFiled(t);
            String exampleName = t.getClass().getName() + "Example";
            Object o = Class.forName(exampleName).newInstance();
            Method m = o.getClass().getMethod("createCriteria");
            Object crite = m.invoke(o, (Object) null);
            for (Field f : fields) {
                if (f.getName().contains("serialVersionUID") || null == f.getAnnotation(ExampleField.class)) {
                    continue;
                }
                Method cm = crite.getClass().getMethod("and" + StrUtils.toUpperCaseFirstOne(f.getName()) + "EqualTo",
                        f.getType());
                Method fm = t.getClass().getMethod("get" + StrUtils.toUpperCaseFirstOne(f.getName()));
                Object result = fm.invoke(t, (Object) null);
                if (result != null && !ObjectUtils.isEmpty(result.toString())) {
                    if (result instanceof String) {
                        Method likem = crite.getClass().getMethod(
                                "and" + StrUtils.toUpperCaseFirstOne(f.getName()) + "Like",
                                f.getType());
                        if (f.getAnnotation(EqualValue.class) != null) {
                            likem = crite.getClass().getMethod(
                                    "and" + StrUtils.toUpperCaseFirstOne(f.getName()) + "EqualTo",
                                    f.getType());
                            likem.invoke(crite, result);
                        } else {
                            likem.invoke(crite, "%" + result + "%");
                        }
                    } else {
                        cm.invoke(crite, result);
                    }
                }
            }
            return (BaseExample) o;
        } catch (Exception e) {
            BizLogger.error(e);
        }
        return null;
    }

    /**
     * 获取对应数据库列的名称
     *
     * @param field
     * @return
     */
    public static String getCloumName(Field field) {
        String cloumName;
        Filed filed = field.getAnnotation(Filed.class);
        if (null != filed) {
            if (ObjectUtils.isNotEmpty(filed.cloum())) {
                cloumName = filed.cloum();
            } else {
                cloumName = StrUtils.humpToUnderline(field.getName(), false);
            }
        } else {
            cloumName = StrUtils.humpToUnderline(field.getName(), false);
        }
        return cloumName;
    }

    /**
     * 获取主键名称
     *
     * @param t
     * @return
     */
    public static String getPramaryKey(BaseEntity t) {
        List<String> fields = getPramaryKeys(t);
        if (CollectionUtils.isEmpty(fields)) {
            return "";
        }
        return fields.get(0);
    }

    /**
     * 获取主建的值
     *
     * @param entity
     * @param id
     * @return
     */
    public static String getPrimayValue(BaseEntity entity, String id) {
        List<String> primaryKeys = getPramaryKeys(entity);
        if (CollectionUtils.isEmpty(primaryKeys)) {
            return "";
        }
        for (String field : primaryKeys) {
            if (id.equalsIgnoreCase(field)) {
                Object o = ReflectionUtils.getFieldValue(entity, field);
                Field f = ReflectionUtils.getField(entity.getClass(), field);
                BaseHandler handler = BeeDataSourceType.getMapping(entity).getTypeByFiled(f).getResovleClass();
                return handler.resovleToString(f, o);
            }
        }
        return "";
    }

    /**
     * 获取多个主键（多主键情况）
     *
     * @param t
     * @return
     */
    public static List<String> getPramaryKeys(BaseEntity t) {
        List<Field> fields = getValidTableFiled(t);
        List<String> names = new ArrayList<>();
        for (Field f : fields) {
            if (f.getAnnotation(Id.class) != null) {
                names.add(f.getName());
            }
        }
        return names;
    }

    /**
     * 获取主建的值(多个)
     *
     * @param entity
     * @return
     */
    public static String getPrimaryValues(BaseEntity entity) {
        List<String> primaryKeys = getPramaryKeys(entity);
        if (CollectionUtils.isEmpty(primaryKeys)) {
            return "";
        }
        List<String> values = new ArrayList<>();
        for (String field : primaryKeys) {
            Object o = ReflectionUtils.getFieldValue(entity, field);
            Field f = ReflectionUtils.getField(entity.getClass(), field);
            BaseHandler handler = BeeDataSourceType.getMapping(entity).getTypeByFiled(f).getResovleClass();
            String value = handler.resovleToString(f, o);
            if (ObjectUtils.isNotEmpty(value))
                values.add(field + "=" + value);
        }
        return StrUtils.join(values, ",");
    }

    /**
     * 获取有效的字段 过滤Transient注解字段
     *
     * @param o
     * @return
     */
    public static List<Field> getValidTableFiled(Object o) {
        return getValidTableFiled(o, true);
    }

    /**
     * 获取有效的字段
     *
     * @param o
     * @param isTransient 是否过滤Transient注解字段
     * @return
     */
    public static List<Field> getValidTableFiled(Object o, boolean isTransient) {
        Field[] fieldArr;
        Field[] supperField = new Field[]{};
        if (o instanceof Class clazz) {//获取proxy父类字段
            fieldArr = clazz.getDeclaredFields();
            ArcShardingProxy proxy = (ArcShardingProxy) clazz.getAnnotation(ArcShardingProxy.class);
            if (proxy != null) {
                supperField = ((Class) o).getSuperclass().getDeclaredFields();
            }
        } else {
            fieldArr = o.getClass().getDeclaredFields();
            ArcShardingProxy proxy = o.getClass().getAnnotation(ArcShardingProxy.class);
            if (proxy != null) {
                supperField = o.getClass().getSuperclass().getDeclaredFields();
            }
        }
        List<Field> fields = new ArrayList<>();
        for (Field f : fieldArr) {
            if ((f.getAnnotation(Transient.class) != null && isTransient)
                    || f.getName().equalsIgnoreCase("serialversionuid")) {
                continue;
            }
            fields.add(f);
        }
        for (Field f : supperField) {
            if ((f.getAnnotation(Transient.class) != null && isTransient)
                    || f.getName().equalsIgnoreCase("serialversionuid")) {
                continue;
            }
            fields.add(f);
        }
        return fields;
    }

    /**
     * 根据不同的jdbctype获取不同的适配器
     *
     * @param head
     * @param entity
     * @param f
     * @return
     */
    public static String getFiledType(String head, BaseEntity entity, Field f) {
        BeeDataSourceType type = BeeDataSourceType.getDataSoureType(TableUtils.getDriverName(entity));
        IBeeProvider handler = type.getHandlerInstance();
        IBeeTypeMapping mapping = (IBeeTypeMapping) handler;
        if (null == mapping.getTypeByFiled(f)) {
            BizLogger.error(entity.getClass().getName() + "--" + f.getName());
        }
        JdbcType jdbcType = mapping.getTypeByFiled(f).getJdbcType();
        if (ObjectUtils.isEmpty(jdbcType)) {
            return head + f.getName() + "}";
        } else {
            if ("clob".equalsIgnoreCase(jdbcType.toString())) {
                return head + f.getName() + ",jdbcType=" + jdbcType + ",typeHandler=" + SerialClobTypeHandler.class.getName() + "}";
            } else if ("blob".equalsIgnoreCase(jdbcType.toString())) {
                return head + f.getName() + ",jdbcType=" + jdbcType + ",typeHandler=" + SerialBlobTypeHandler.class.getName() + "}";
            } else {
                return head + f.getName() + ",jdbcType=" + jdbcType + "}";
            }
        }
    }

    /**
     * 查询返回的MAP 转为对象
     *
     * @param o
     * @param t
     * @param <T>
     * @return
     */
    public static <T extends BaseEntity> List<T> getListFromListMap(Object o, T t) {
        return (List<T>) getListFromListMap(o,t.getClass(),null);
    }

    public static <T extends BaseEntity> List<T> getListFromListMap(Object o, Class<T> clazz, BeeComplexQueryWrapper wrapper) {
        if (ObjectUtils.isEmpty(o)) {
            return Collections.emptyList();
        }
        List<Map<String, Object>> mapList;

        if (o instanceof List<?> list) {
            // 如果是列表，确保列表非空且元素为 Map
            if (list.isEmpty() || !(list.get(0) instanceof Map<?, ?>)) {
                return Collections.emptyList();
            }
            mapList = (List<Map<String, Object>>) list;
        } else if (o instanceof Map<?, ?> map) {
            // 如果是单个 Map，则将其封装为单元素列表
            mapList = Collections.singletonList((Map<String, Object>) map);
        } else {
            return Collections.emptyList(); // 其他类型返回空列表
        }

        List<Field> fields = SqlProvider.getValidTableFiled(clazz, false);
        Map<String, Field> fieldMap = new HashMap<>();

        for (Field field : fields) {
            Filed filedAnnotation = field.getAnnotation(Filed.class);
            if (filedAnnotation != null && ObjectUtils.isNotEmpty(filedAnnotation.cloum())) {
                fieldMap.put(filedAnnotation.cloum().toLowerCase(), field);
            }else{
                fieldMap.put(field.getName().toLowerCase(), field);
            }
        }

        IBeeTypeMapping mapping = BeeDataSourceType.getMapping(ReflectionUtils.newInstance(clazz));

        return ((List<Map<String, Object>>) mapList).stream()
                .filter(Objects::nonNull)
                .map(map -> {
                    T tmp = (T) ReflectionUtils.newInstance(clazz);
                    Set<String> difference = new HashSet(fields.stream().map(item->item.getName()).toList());
                    difference.removeAll(map.keySet());
                    if(!CollectionUtils.isEmpty(difference)){//如果有多余属性
                        for(String diff : difference){
                            Field field = fieldMap.get(diff.toLowerCase());
                            if (field!=null&&wrapper!=null && !CollectionUtils.isEmpty(wrapper.getJoinClass()) && wrapper.getJoinClass().contains(field.getType())) {
                                // 递归调用以处理关联类
                                List<?> relatedList = getListFromListMap(map, (Class<T>) field.getType(),null);
                                if(!CollectionUtils.isEmpty(relatedList)) {
                                    ReflectionUtils.setFieldValue(tmp, field.getName(), relatedList.get(0));
                                }
                            }
                        }

                    }
                    map.forEach((key, value) -> {
                        if (ObjectUtils.isEmpty(value)) return;
                        String lowerKey = key.toLowerCase();
                        Field field = fieldMap.get(lowerKey);
                        if (field != null) {
                            BeeTypeEntity fieldTypeMapping = mapping.getTypeByFiled(field);
                            if (fieldTypeMapping != null) {
                                BaseHandler handler = fieldTypeMapping.getResovleClass();
                                if (handler != null) {
                                    Object resolvedValue = handler.resovleResult(value);
                                    ReflectionUtils.setFieldValue(tmp, field.getName(), resolvedValue);
                                }
                            }
                        }
                    });
                    return tmp;
                })
                .collect(Collectors.toList());
    }
}
